這篇教學會介紹延伸「人臉偵測」文章的範例,搭配 OpenCV 馬賽克的效果,自動偵測影像中的人臉,並將人臉加上馬賽克。
原文參考:OpenCV 偵測人臉,自動加馬賽克
因為程式中的 OpenCV 會需要使用鏡頭或 GPU,所以請使用本機環境 ( 參考:使用 Python 虛擬環境 ) 或使用 Anaconda Jupyter 進行實作 ( 參考:使用 Anaconda ) ,並安裝 OpenCV 函式庫 ( 參考:OpenCV 函式庫 )。

OpenCV 的官方 Github 提供了許多訓練好的特徵模型,只需要下載後就能使用,請從下方網址進行下載,下載後將 xml 檔案和 Python 的程式檔放在同一層目錄下。
- OpenCV 官方 Github:https://github.com/opencv/opencv/tree/4.x/data
- 人臉特徵模型:haarcascade_frontalface_default.xml
將「人臉偵測」和「馬賽克效果」兩篇文章的範例結合,當影像中偵測到人臉時,透過 x、y 坐標和 w、h 長寬,就能定義馬賽克的位置和大小,下面的程式執行後,會自動將蒙娜麗莎的臉加上馬賽克。
import cv2
img = cv2.imread('mona.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 影像轉換成灰階
face_cascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml") # 載入人臉偵測模型
faces = face_cascade.detectMultiScale(gray,1.2,3)  # 開始辨識影像中的人臉
for (x, y, w, h) in faces:
    mosaic = img[y:y+h, x:x+w]   # 馬賽克區域
    level = 15                   # 馬賽克程度
    mh = int(h/level)            # 根據馬賽克程度縮小的高度
    mw = int(w/level)            # 根據馬賽克程度縮小的寬度
    mosaic = cv2.resize(mosaic, (mw,mh), interpolation=cv2.INTER_LINEAR) # 先縮小
    mosaic = cv2.resize(mosaic, (w,h), interpolation=cv2.INTER_NEAREST)  # 然後放大
    img[y:y+h, x:x+w] = mosaic   # 將指定區域換成馬賽克區域
cv2.imshow('oxxostudio', img)
cv2.waitKey(0)   # 按下任意鍵停止
cv2.destroyAllWindows()

如果有多張人臉,也可以順利偵測,並將偵測到的人臉加上馬賽克 ( 圖片為 Fusilamientos de Torrijos y sus compañeros en las playas de Málaga
)。

延伸「讀取並播放影片」文章的範例,搭配人臉偵測的方法,就可以即時偵測攝影鏡頭裡的人臉。
import cv2
cap = cv2.VideoCapture(0)
face_cascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
if not cap.isOpened():
    print("Cannot open camera")
    exit()
while True:
    ret, frame = cap.read()
    if not ret:
        print("Cannot receive frame")
        break
    frame = cv2.resize(frame,(480,300))              # 縮小尺寸,避免尺寸過大導致效能不好
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)   # 影像轉轉灰階
    faces = face_cascade.detectMultiScale(gray)      # 偵測人臉
    for (x, y, w, h) in faces:
        mosaic = frame[y:y+h, x:x+w]
        level = 15
        mh = int(h/level)
        mw = int(w/level)
        mosaic = cv2.resize(mosaic, (mw,mh), interpolation=cv2.INTER_LINEAR)
        mosaic = cv2.resize(mosaic, (w,h), interpolation=cv2.INTER_NEAREST)
        frame[y:y+h, x:x+w] = mosaic
    cv2.imshow('oxxostudio', frame)
    if cv2.waitKey(1) == ord('q'):
        break    # 按下 q 鍵停止
cap.release()
cv2.destroyAllWindows()

大家好,我是 OXXO,是個即將邁入中年的斜槓青年,我已經寫了超過 400 篇 Python 的教學,有興趣可以參考下方連結呦~ ^_^